/**************************************************************************************************
* Title: SumPlane.inl
* Author: Gael Huber
* Description: Implements methods for a plane
**************************************************************************************************/

/**************************************************************************************************
* Default constructor
**************************************************************************************************/
inline Plane::Plane(void)
	: a(0.0f), b(0.0f), c(0.0f), d(0.0f)
{ }

/**************************************************************************************************
* Constructor from array
**************************************************************************************************/
inline Plane::Plane(const float* f)
	: a(f[0]), b(f[1]), c(f[2]), d(f[3])
{ }

/**************************************************************************************************
* Constructor from specified points
**************************************************************************************************/
inline Plane::Plane(float a, float b, float c, float d)
	: a(a), b(b), c(c), d(d)
{ }

/**************************************************************************************************
* Copy-constructor
**************************************************************************************************/
inline Plane::Plane(const Plane& rhs)
	: a(rhs.a), b(rhs.b), c(rhs.c), d(rhs.d)
{ }

/**************************************************************************************************
* Destructor
**************************************************************************************************/
inline Plane::~Plane(void)
{ }

/**************************************************************************************************
* Cast object as float array
**************************************************************************************************/
inline Plane::operator float*(void) {
	return (float*) this;
}

/**************************************************************************************************
* Cast object as const float array
**************************************************************************************************/
inline Plane::operator const float*(void) const {
	return (const float*) this;
}

/**************************************************************************************************
* Assignment operator
**************************************************************************************************/
inline Plane& Plane::operator=(const Plane& rhs) {
	if(this == &rhs)
		return *this;
	
	a = rhs.a;
	b = rhs.b;
	c = rhs.c;
	d = rhs.d;
	return *this;
}

/**************************************************************************************************
* Multiply the plane by a scalar value
**************************************************************************************************/
inline Plane& Plane::operator*=(float rhs) {
	a *= rhs;
	b *= rhs;
	c *= rhs;
	d *= rhs;
	return *this;
}

/**************************************************************************************************
* Divide the plane by a scalar value
**************************************************************************************************/
inline Plane& Plane::operator/=(float rhs) {
	const float f = 1.0f / rhs;
	a *= f;
	b *= f;
	c *= f;
	d *= f;
	return *this;
}

/**************************************************************************************************
* Returns a positive version of this plane
**************************************************************************************************/
inline Plane Plane::operator+(void) const {
	return Plane(*this);
}

/**************************************************************************************************
* Returns a negated version of this plane
**************************************************************************************************/
inline Plane Plane::operator-(void) const {
	return Plane(-a, -b, -c, -d);
}

/**************************************************************************************************
* Returns the plane multiplied by a scalar
**************************************************************************************************/
inline Plane Plane::operator*(float rhs) const {
	return Plane(a*rhs, b*rhs, c*rhs, d*rhs);
}

/**************************************************************************************************
* Returns the plane divided by a scalar
**************************************************************************************************/
inline Plane Plane::operator/(float rhs) const {
	const float f = 1.0f / rhs;
	return Plane(a*f, b*f, c*f, d*f);
}

/**************************************************************************************************
* Returns a plane multiplied by a scalar
**************************************************************************************************/
inline Plane operator*(float lhs, const Plane& rhs) {
	return Plane(lhs*rhs.a, lhs*rhs.b, lhs*rhs.c, lhs*rhs.d);
}

/**************************************************************************************************
* Equivalence
**************************************************************************************************/
inline bool Plane::operator==(const Plane& rhs) const {
	return (a == rhs.a && b == rhs.b && c == rhs.c && d == rhs.d);
}

/**************************************************************************************************
* Non-equivalence
**************************************************************************************************/
inline bool Plane::operator!=(const Plane& rhs) const {
	return (a != rhs.a || b != rhs.b || c != rhs.c || d != rhs.d);
}

/**************************************************************************************************
* Returns the dot product of a plane with a 4D vector. ax + by + cz + dw
**************************************************************************************************/
inline float PlaneDot(const Plane* pP, const Vector4* pV) {
	return pP->a*pV->x + pP->b*pV->y + pP->c*pV->z + pP->d*pV->w;
}

/**************************************************************************************************
* Returns the dot product of a plane with a 3D vector. ax + by + cz + d
**************************************************************************************************/
inline float PlaneDotCoord(const Plane* pP, const Vector3* pV) {
	return pP->a*pV->x + pP->b*pV->y + pP->c*pV->z + pP->d;
}

/**************************************************************************************************
* Returns the doct product of a plane with the plane normal. ax + by + cz
**************************************************************************************************/
inline float PlaneDotNormal(const Plane* pP, const Vector3* pV) {
	return pP->a*pV->x + pP->b*pV->y + pP->c*pV->x;
}

/**************************************************************************************************
* Returns the a plane multiplied by a scalar to scale the plane
**************************************************************************************************/
inline Plane* PlaneScale(Plane* pOut, const Plane* pP, float s) {
	pOut->a = pP->a * s;
	pOut->b = pP->b * s;
	pOut->c = pP->c * s;
	pOut->d = pP->d * s;
	return pOut;
}